#!/usr/bin/env python

import pygame
from pygame.locals import *
import random
import sys

import pygamesvg

import debug
import image
import rule
import text
import tile
import unit

from debug import *

TITLE    = 'Boop'
S_WIDTH  = 480
S_HEIGHT = 270
FPS      = 30

SCROLL_MARGIN = 20

TO_N = 0
TO_L = -1
TO_R = 1
TO_D = -3
TO_U = 3
TO_UL = TO_L + TO_U
TO_UR = TO_R + TO_U
TO_DL = TO_L + TO_D
TO_DR = TO_R + TO_D

scroll_dir = { TO_N: 'no_direction',
               TO_L: 'left',
               TO_R: 'right',
               TO_U: 'up',
               TO_D: 'down',
               TO_UL: 'upper_left',
               TO_UR: 'upper_right',
               TO_DL: 'lower_left',
               TO_DR: 'lower_right'
              }
def main():
  pygame.init()
  
  screen = pygame.display.set_mode((S_WIDTH, S_HEIGHT), HWACCEL|DOUBLEBUF)
  #screen = pygame.display.set_mode((S_WIDTH, S_HEIGHT))
  
  print pygame.display.get_driver()
  disp_info = pygame.display.Info()
  print disp_info
  
  screen.fill((0, 0, 0))
  
  text.load_font('vlgothic.ttf', 'dontcare', size=14, set_as_default=True)
  text.load_font('vlgothic.ttf', 'vl_small', size=12)
  
  t_size = (30, 30)
  
  tile_engine = tile.TileEngine(tile_wh=t_size)
  
  
  
  #cursor = image.Still(image.svg_file_to_surface(file('map_cursor.svg'), size=t_size))
  #cursor = image.SmoothZoom('map_cursor.svg', frames=60, start=(1.0, 1.0), stop=(0.5, 0.5))
  #cursor = image.Still(image.svg_file_to_surface(file('map_cursor.svg'), scale=(0.1, 0.1)))
  cursor = unit.load_cursor(cursor_normal=image.SmoothAlpha('map_cursor.svg', 
                                frames=60, start=1.0, stop=0.5, size=t_size),
                            cursor_attack=image.Still(
                                image.svg_file_to_surface(file('crosshair.svg'), size=t_size)))
  #h_tile = image.SmoothAlpha('highlight_tile.svg', frames=60, start=0.7, stop=0.2, scale=(0.1, 0.1))
  h_tile = image.Still(image.svg_file_to_surface(file('highlight_tile.svg'), size=t_size, alpha=0.5))
  
  grass = image.svg_file_to_surface(file('t_grass.svg'), size=t_size)
  #grass = pygame.image.load('t_grass.png')
  #plains = image.svg_file_to_surface(file('t_plains.svg'), size=t_size)
  water = image.svg_file_to_surface(file('t_water.svg'), size=t_size)
  forest = pygame.image.load('t_forest.png')
  forest2 = pygame.image.load('t_forest_2.png')
  mountain = pygame.image.load('t_mountain.png')
  #blank = image.svg_file_to_surface(file('t_blank.svg'), size=t_size)
  '''
  water_surfaces = {  (tile.TERRAIN_WATER, tile.TERRAIN_LAND, tile.TERRAIN_WATER, tile.TERRAIN_WATER): pygame.image.load('cliff_r.png'),
                      (tile.TERRAIN_LAND, tile.TERRAIN_WATER, tile.TERRAIN_WATER, tile.TERRAIN_WATER): pygame.image.load('cliff_t.png'),
                      (tile.TERRAIN_WATER, tile.TERRAIN_WATER, tile.TERRAIN_LAND, tile.TERRAIN_WATER): pygame.image.load('cliff_b.png'),
                      tile.DIR_NONE: water
                    }
  '''
  '''
  water_surfaces = { (tile.TERRAIN_WATER, None, tile.TERRAIN_LAND, None, tile.TERRAIN_WATER, tile.TERRAIN_WATER, tile.TERRAIN_WATER, tile.TERRAIN_WATER): pygame.image.load('beach_e.png'),
                      tile.DIR_NONE: water
                    }
  '''
  water_surfaces = tile.load_water_surfaces('beach.*png', base_dir = '.')
  water_surfaces[tile.DIR_NONE] = water
  
  tt_grass = tile.TileType(name='grass', long_name='Grass', short_name='Grss', surface=grass, defense_value=1)
  #tt_plains = tile.TileType(name='plains', long_name='Plains', surface=plains)
  #tt_water = tile.TileType(name='water', long_name='Sea', surface=water, 
  #                        terrain_type=tile.TERRAIN_WATER)
  tt_forest = tile.TileType(name='forest', long_name='Forest', short_name='Frst', surface=forest, defense_value=2)
  tt_forest_2 = tile.TileType(name='forest', long_name='Forest', short_name='Frst', surface=forest2, defense_value=2)
  tt_mountain = tile.TileType(name='mountain', long_name='Mountain', short_name='Mtn', surface=mountain, defense_value=4)
  
  tt_water = tile.CSensitiveTileType(name='water', long_name='Sea', short_name='Sea', surfaces=water_surfaces,
                                    terrain_type=tile.TERRAIN_WATER, by_name=False)
  
  tt_factory = tile.ColorableTileType(name='base', long_name='Base', short_name='Base',
                                      defense_value=3,
                                      svg_data=file('t_factory.svg').read(),
                                      tile_wh=(30, 47),
                                      dark_color='737373',
                                      light_color='909090')
  tt_factory.add_color('ee1000')
  
  
  #tt_plains = tile.TileType(plains, 'plains', 'Plains')
  #tt_water = tile.TileType(water, 'water', 'Water', tile.TERRAIN_WATER)
  #tt_blank = tile.TileType(blank, 'blank_tile', 'Blank Tile')
  
  g = tile_engine.register_tile_type(tt_grass, id=0)
  f = tile_engine.register_tile_type(tt_forest)
  f2 = tile_engine.register_tile_type(tt_forest_2)
  m = tile_engine.register_tile_type(tt_mountain)
  fa = tile_engine.register_tile_type(tt_factory)
  #p = tile_engine.register_tile_type(tt_plains)
  w = tile_engine.register_tile_type(tt_water, id=1)
  #bl = tile_engine.register_tile_type(tt_blank)
  '''
  map = [[g, p, p, p, p, p, p],
         [g, w, w, w, w, w, w],
         [g, w, w, g, g, w, w],
         [g, w, w, g, g, w, w],
         [g, w, w, w, w, w, w]
        ]
  '''
  tiles = [g, w]
  
  map = [[w, w, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, w, w],
         [w, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, w],
         [w, g, g, g, f, g, g, w, g, g, g, g, w, g, g, g, g, g, g],
         [g, g, g, f, f2, g, g, w, w, w, w, w, w, g, g, g, g, g, g],
         [m, g, fa, g, f, g, g, g, w, w, w, g, g, g, g, g, g, g, g],
         [g, m, g, m, m, w, g, g, w, w, w, w, g, g, g, g, g, g, g],
         [m, g, g, f, m, w, w, w, w, w, w, w, g, g, g, g, g, g, g],
         [g, g, g, g, g, g, g, w, w, w, w, w, w, g, g, g, g, g, g],
         [g, g, g, g, g, w, g, f2, f, f, f2, g, w, w, g, g, g, g, g],
         [g, g, g, g, w, w, w, g, g, g, g, g, w, g, g, g, g, g, g],
         [g, g, g, g, g, w, w, g, g, g, g, w, w, g, g, g, g, g, g],
         [g, g, g, g, g, g, g, g, g, g, g, g, w, g, g, g, g, g, g],
         [g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g],
         [g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g],
         [g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g],
         [g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g],
         [g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g],
         [w, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, w]
         
        ]
  
  '''
  map = []
  w_h = 50
  for y in range(0, w_h):
    curr_row = []
    for x in range (0, w_h):
      curr_row.append(tiles[random.randint(0, len(tiles) - 1)])
    map.append(curr_row)
  '''
  tile_engine.load_map(map)
  
  map_rect = tile_engine.update().get_rect()
  info('map_dimen=(%d, %d)' % (map_rect.w, map_rect.h))
  
  rule_engine = rule.RuleEngine()
  
  rule_engine.register_rule(rule.Rule(rule.TYPE_PLACEMENT,
                            unit_class=unit.CLASS_TREADS,
                            terrain_type=tile.TERRAIN_WATER,
                            can_place=False))
  
  rule_engine.register_rule(rule.Rule(rule.TYPE_PLACEMENT,
                            unit_class=unit.CLASS_TREADS,
                            tile_name='mountain',
                            can_place=False))
  
  rule_engine.register_rule(rule.Rule(rule.TYPE_MOVEMENT, 
                            unit_class=unit.CLASS_TREADS,
                            terrain_type=tile.TERRAIN_WATER,
                            cost=unit.MOV_INF))
  
  rule_engine.register_rule(rule.Rule(rule.TYPE_MOVEMENT, 
                            unit_class=unit.CLASS_TREADS,
                            tile_name='mountain',
                            cost=unit.MOV_INF))
  
  rule_engine.register_rule(rule.Rule(rule.TYPE_MOVEMENT, 
                            unit_class=unit.CLASS_TREADS,
                            tile_name='forest',
                            cost=2))
  
  
  b_anim = image.Still(image.svg_file_to_surface(file('metal_ball.svg'), size=t_size))
  
  ball = unit.UnitType('Ball', unit.CLASS_TREADS,
                        max_hp=100, max_mp=4, max_fuel=90,
                        state_normal=b_anim)
  tank = unit.UnitType('Tank', unit.CLASS_TREADS,
                        max_hp=10, max_mp=5, max_fuel=70,
                        state_normal=image.Still(pygame.image.load('tank.png')))
  
  b_unit    = unit.Unit(ball)
  b_unit2   = unit.Unit(ball)
  
  t_unit1 = unit.Unit(tank)
  
  unit_engine = unit.UnitEngine(tile_engine, rule_engine)
  unit_engine.set_mv_highlight_tile(h_tile)
  unit_engine.set_arrow(unit.load_arrow('arrow', size=t_size))
  unit_engine.set_cursor(cursor)
  
  unit_engine.place_unit(b_unit, (2, 5))
  unit_engine.place_unit(b_unit2, (1, 6))
  unit_engine.place_unit(t_unit1, (0, 5))
  
  info_overlay = tile.InfoOverlay(tile_engine, 
                                  unit_engine,
                                  font=text.get_font('vl_small')
                                  )
  
  viewport = tile.Viewport((S_WIDTH, S_HEIGHT), unit_engine)
  viewport.register_cursor_listener(unit_engine)
  viewport.register_cursor_listener(info_overlay)
  
  clock = pygame.time.Clock()
  
  scroll_state = TO_N
  
  exit = False
  
  clicked = False
  m_button = None
  mouse_x, mouse_y = -1, -1
  while True:
    if exit: break
    
    f_b_time = pygame.time.get_ticks()
    for event in pygame.event.get():
      if event.type == pygame.QUIT: exit = True
      elif event.type == pygame.MOUSEMOTION:
        mouse_x, mouse_y = event.pos
      elif event.type == pygame.MOUSEBUTTONUP:
        mouse_x, mouse_y = event.pos
        m_button = event.button
        clicked = True
    
    if mouse_x != -1 and mouse_y != -1:
      dir = mouse_x < SCROLL_MARGIN and TO_L or 0
      dir = mouse_x > S_WIDTH - SCROLL_MARGIN and dir + TO_R or dir
      dir = mouse_y < SCROLL_MARGIN and dir + TO_U or dir
      dir = mouse_y > S_HEIGHT - SCROLL_MARGIN and dir + TO_D or dir
      scroll_state = dir

    ll = scroll_state in [TO_L, TO_DL, TO_UL]
    rr = scroll_state in [TO_R, TO_DR, TO_UR]
    uu = scroll_state in [TO_U, TO_UL, TO_UR]
    dd = scroll_state in [TO_D, TO_DL, TO_DR]
    viewport.set_pan_directions((ll, rr, uu, dd))
    
    if mouse_x != -1 and mouse_y != -1:
      viewport.set_cursor_position((mouse_x, mouse_y))
    
    if clicked:
      print 'clicked, %s' % (m_button)
      viewport.set_cursor_select((mouse_x, mouse_y))
      clicked = False
    
    r = screen.blit(viewport.update(), (0, 0))
    
    ov_surf = info_overlay.update()
    if ov_surf is not None:
      blit_x, blit_y = 0, S_HEIGHT - ov_surf.get_rect().h
      if mouse_x < S_WIDTH / 2:
        blit_x = S_WIDTH - ov_surf.get_rect().w
      rr = screen.blit(ov_surf, (blit_x, blit_y))
    
    
    pygame.display.flip()
    
    f_e_time = pygame.time.get_ticks()
    #debug('%d msecs since previous frame.' % (f_e_time - f_b_time))
    
    debug('%d msecs since previous tick.' % (clock.tick(FPS)))
  
  pygame.quit()

if __name__ == "__main__":
  main()
